<!DOCTYPE html>
<html lang="zh">
<head>
    <title>3D物联网</title>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>
    <link rel="shortcut icon" href="./images/icon.png"/>

    <meta http-equiv="pragma" content="no-cache"/>
    <meta http-equiv="cache-control" content="no-cache"/>
    <meta http-equiv="expires" content="0"/>
</head>

<body>
<link rel="stylesheet" href="./css/main.css"/>

<script src="../js/vue.min.js"></script>
<script src="../js/axios.min.js"></script>

<script src="../js/threejs/libs/draco/draco_encoder.js"></script>

<link rel="stylesheet" href="../js/threejs/libs/codemirror/codemirror.css"/>
<link rel="stylesheet" href="../js/threejs/libs/codemirror/theme/monokai.css"/>
<script src="../js/threejs/libs/codemirror/codemirror.js"></script>
<script src="../js/threejs/libs/codemirror/mode/javascript.js"></script>
<script src="../js/threejs/libs/codemirror/mode/glsl.js"></script>

<script src="../js/threejs/libs/esprima.js"></script>
<script src="../js/threejs/libs/jsonlint.js"></script>
<script src="../js/threejs/libs/glslprep.min.js"></script>

<link rel="stylesheet" href="../js/threejs/libs/codemirror/addon/dialog.css"/>
<link rel="stylesheet" href="../js/threejs/libs/codemirror/addon/show-hint.css"/>
<link rel="stylesheet" href="../js/threejs/libs/codemirror/addon/tern.css"/>

<script src="../js/threejs/libs/codemirror/addon/dialog.js"></script>
<script src="../js/threejs/libs/codemirror/addon/show-hint.js"></script>
<script src="../js/threejs/libs/codemirror/addon/tern.js"></script>
<script src="../js/threejs/libs/acorn/acorn.js"></script>
<script src="../js/threejs/libs/acorn/acorn_loose.js"></script>
<script src="../js/threejs/libs/acorn/walk.js"></script>
<script src="../js/threejs/libs/ternjs/polyfill.js"></script>
<script src="../js/threejs/libs/ternjs/signal.js"></script>
<script src="../js/threejs/libs/ternjs/tern.js"></script>
<script src="../js/threejs/libs/ternjs/def.js"></script>
<script src="../js/threejs/libs/ternjs/comment.js"></script>
<script src="../js/threejs/libs/ternjs/infer.js"></script>
<script src="../js/threejs/libs/ternjs/doc_comment.js"></script>
<script src="../js/threejs/libs/tern-threejs/threejs.js"></script>
<script type="module">
  import * as THREE from '../js/threejs/build/three.module.js'

  import {Editor} from './js/Editor.js'
  import {Viewport} from './js/Viewport.js'
  import {Toolbar} from './js/Toolbar.js'
  import {Script} from './js/Script.js'
  import {Sidebar} from './js/Sidebar.js'
  import {Menubar} from './js/Menubar.js'
  import {AddObjectCommand} from '../js/threejs/commands/AddObjectCommand.js'
  import {RemoveObjectCommand} from '../js/threejs/commands/RemoveObjectCommand.js'

  window.URL = window.URL || window.webkitURL
  window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder

  Number.prototype.format = function () {
    return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
  }

  //

  let editor = new Editor()

  window.editor = editor // Expose editor to Console
  window.THREE = THREE // Expose THREE to APP Scripts and Console

  let viewport = new Viewport(editor)
  document.body.appendChild(viewport.dom)

  let sidebar = new Sidebar(editor)
  document.body.appendChild(sidebar.dom)

  let toolbar = new Toolbar(editor)
  document.body.appendChild(toolbar.dom)

  let script = new Script(editor)
  document.body.appendChild(script.dom)

  let menubar = new Menubar(editor)
  document.body.appendChild(menubar.dom)

  editor.storage.init(function () {
      // 2、后台获取场景配置信息
      editor.storageRemote.getDeployConfig().then((deployConfig) => {
          // 读取浏览器缓存
          editor.storage.get(function (state) {
              if (state !== undefined) {
                  console.log('>>>>>>>>>>>>>> 缓存加载模型 <<<<<<<<<<<<<')
                  if (isJSON(state)) {
                      editor.fromJSON(state).then(scene => {
                          console.log('缓存加载模型 完成', scene)
                          /* 读取场景信息和设备信息，遍历 */
                          deployConfigInit(deployConfig)
                      })
                  }
              } else {
                  // 没有缓存时，直接执行模型配置初始化
                  console.log('>>>>>>>>>>>>>> 后台加载模型 <<<<<<<<<<<<<')
                  deployConfigInit(deployConfig)
              }
              setSceneLight()
          })
      })

    /**
     * 模型配置初始化
     * @author zhouwr
     */
    let deployConfigInitTimeout
      function deployConfigInit(deployConfig) {
          console.log('>>>>>>>>>> 模型配置初始化 <<<<<<<<<')
          clearTimeout(deployConfigInitTimeout)
          // 拿到场景配置信息中的模型文件，以","分割
          let modelFiles = deployConfig['modelFile'].split(',') // 后台请求的部署配置数据：场景数据
          for (const file of modelFiles) {
              let sceneConfig = JSON.parse(JSON.stringify(deployConfig))
              sceneConfig.modelFile = file
              delete sceneConfig.deviceInstances
              objectQueryCompared('file', file, sceneConfig)
          }
          // 2、比对设备
          let deviceConfs = editor.deployConfig['deviceInstances']
          if (deviceConfs !== undefined && deviceConfs.length > 0) {
              for (const deviceConf of deviceConfs) {
                objectQueryCompared('uuid', deviceConf.id, deviceConf)
              }
          }
      }

    /**
     * 设备查找并对比
     * @author zhouwr
     * @propertyName 查询关键字的名称
     * @propertyValue 查询关键字的值
     * @config 配置信息
     * @TODO 后台把模型的文件修改后，前端请求文件时，要替换掉模型对象
     */
    function objectQueryCompared(propertyName, propertyValue, config) {
        let object = editor.scene.getObjectByProperty(propertyName, propertyValue)
        if (object) {
            // 找到对象
            console.log('找到对象', propertyName, propertyValue, config.name)
            // 先拿到对象的medel跟配置信息的文件名对比
            if (object.file === config.modelFile) {
                // 模型文件相等，直接配置，无需重新请求模型文件
                editor.configObj(object, config)
            } else {
                // 不想等
                console.log(`1、模型[${object.name}]的文件[${object.file}]与配置信息文件[${config.modelFile}]不匹配`)
                // 1、先删除模型对象
                console.log(`2、删除对象[${object.name}]`)
                new RemoveObjectCommand(editor, object)
                // 重新获取对象
                getObject(config)
            }
        } else {
            // 找不到对象，匹配不成功，后台加载模型文件
            console.log('找不到对象', propertyName, propertyValue, config.name)
            getObject(config)
        }
    }
      function getObject(config) {
          /* 查找相同文件的现有对象 */
          const existObj = editor.scene.getObjectByProperty('file', config.modelFile);
          editor.signals.objectAllConfiged.active = false
          if(existObj) {
              console.log(`克隆已存在的[${existObj.name}]模型`)
              const clone = existObj.clone();
              editor.configObj(clone, config)
              editor.addObject(clone)
          } else {
              console.log(`3、重新远程加载模型`)
              editor.loaderRemote.loadFiles(config)
          }
      }
    /**
     * 判断从缓存读出来的JSON是否合法
     * @author zhouwr
     */
    function isJSON(json) {
      if (json.length < 36) {
        return false
      } else {
        return true
      }
    }

    /**
     * 设置灯光
     * @author zhouwr
     */
    function setSceneLight() {
      setTimeout(function () {
        if (!editor.scene.getObjectByName('AmbientLight')) {
          let color = 0x222222
          let light = new THREE.AmbientLight(color)
          light.name = 'AmbientLight'
          editor.execute(new AddObjectCommand(editor, light))
        }
        if (!editor.scene.getObjectByName('DirectionalLight')) {
          let color = 0xffffff
          let intensity = 1
          let light = new THREE.DirectionalLight(color, intensity)
          light.name = 'DirectionalLight'
          light.target.name = 'DirectionalLight Target'
          light.position.set(5, 10, 7.5)
          editor.execute(new AddObjectCommand(editor, light))
        }
      }, 100)
    }

    let timeout

    function saveState() {
      if (editor.config.getKey('autosave') === false) {
        return
      }
      clearTimeout(timeout)
      timeout = setTimeout(function () {
        editor.signals.savingStarted.dispatch()
        timeout = setTimeout(function () {
          editor.storage.set(editor.toJSON())
          editor.signals.savingFinished.dispatch()
          editor.config.setKey('autosave', false)
        }, 100)
      }, 1000)
    }

    let signals = editor.signals

    // signals.geometryChanged.add(saveState)
    signals.objectAdded.add(saveState)
    // signals.objectChanged.add(saveState)
    signals.objectRemoved.add(saveState)
    // signals.materialChanged.add(saveState)
    // signals.sceneBackgroundChanged.add(saveState)
    // signals.sceneFogChanged.add(saveState)
    // signals.sceneGraphChanged.add(saveState)
    // signals.scriptChanged.add(saveState)
    // signals.historyChanged.add(saveState)
    // zhouwr
    signals.objectAllConfiged.add(saveState)
  })

  //

  document.addEventListener(
    'dragover',
    function (event) {
      event.preventDefault()
      event.dataTransfer.dropEffect = 'copy'
    },
    false
  )

  document.addEventListener(
    'drop',
    function (event) {
      event.preventDefault()

      if (event.dataTransfer.types[0] === 'text/plain') return // Outliner drop

      if (event.dataTransfer.items) {
        // DataTransferItemList supports folders

        editor.loader.loadItemList(event.dataTransfer.items)
      } else {
        editor.loader.loadFiles(event.dataTransfer.files)
      }
    },
    false
  )

  function onWindowResize() {
    editor.signals.windowResize.dispatch()
  }

  window.addEventListener('resize', onWindowResize, false)
  onWindowResize()

  // ServiceWorker

  if ('serviceWorker' in navigator) {
    try {
      navigator.serviceWorker.register('../js/threejs/libs/sw.js')
    } catch (error) {
    }
  }
</script>
<script src="../js/threejs/libs/signals.min.js"></script>
</body>
</html>
